****************************** Java Stored Function/Procedure ****************************** Stored functions and procedures are used to implement complicated program logic that is not possible with SQL. They allow users to manipulate data more easily. Stored functions/procedures are blocks of code that have a flow of commands for data manipulation and are easy to manipulate and administer. CUBRID supports to develop stored functions and procedures in Java. Java stored functions/procedures are executed on the JVM (Java Virtual Machine) hosted by CUBRID. You can call Java stored functions/procedures from SQL statements or from Java applications using JDBC. The advantages of using Java stored functions/procedures are as follows: * **Productivity and usability** : Java stored functions/procedures, once created, can be reused anytime. They can be called from SQL statements or from Java applications using JDBC. * **Excellent interoperability and portability** : Java stored functions/procedures use the Java Virtual Machine. Therefore, they can be used on any system where the Java Virtual Machine is available. .. _jsp_environment-configuration: Environment Configuration for Java Stored Function/Procedure ============================================================ To use Java-stored functions/procedures in CUBRID, you must have JRE (Java Runtime Environment) 1.6 or better installed in the environment where the CUBRID server is installed. You can download JRE from the Developer Resources for Java Technology (`http://java.sun.com `_). If the java_stored_procedure parameter in the CUBRID configuration file (cubrid.conf) is set to yes, CUBRID 64-bit needs a 64-bit Java Runtime Environment, and CUBRID 32-bit needs a 32-bit Java Runtime Environment. For example, when you run CUBRID 64-bit in the system in which a 32-bit JAVA Runtime Environment is installed, the following error may occur. :: % cubrid server start demodb This may take a long time depending on the amount of recovery works to do. WARNING: Java VM library is not found : /usr/java/jdk1.6.0_15/jre/lib/amd64/server/libjvm.so: cannot open shared object file: No such file or directory. Consequently, calling java stored procedure is not allowed Execute the following command to check the JRE version if you have it already installed in the system. :: % java -version Java(TM) SE Runtime Environment (build 1.6.0_05-b13) Java HotSpot(TM) 64-Bit Server VM (build 10.0-b19, mixed mode) Windows Environment ------------------- For Windows, CUBRID loads the **jvm.dll** file to run the Java Virtual Machine. CUBRID first locates the **jvm.dll** file from the **PATH** environment variable and then loads it. If it cannot find the file, it uses the Java runtime information registered in the system registry. You can configure the **JAVA_HOME** environment variable and add the directory in which the Java executable file is located to **Path**, by executing the command as follows: For information on configuring environment variables using GUI, see Installing and Configuring JDBC. * An example of installing 64 Bit JDK 1.6 and configuring the environment variables :: % set JAVA_HOME=C:\jdk1.6.0 % set PATH=%PATH%;%JAVA_HOME%\jre\bin\server * An example of installing 32 Bit JDK 1.6 and configuring the environment variables :: % set JAVA_HOME=C:\jdk1.6.0 % set PATH=%PATH%;%JAVA_HOME%\jre\bin\client To use other vendor's implementation instead of Sun's Java Virtual Machine, add the path of the **jvm.dll** file to the **PATH** variable during the installation. Linux/UNIX Environment ---------------------- For Linux/UNIX environment, CUBRID loads the **libjvm.so** file to run the Java Virtual Machine. CUBRID first locates the **libjvm.so** file from the **LD_LIBRARY_PATH** environment variable and then loads it. If it cannot find the file, it uses the **JAVA_HOME** environment variable. For Linux, glibc 2.3.4 or later versions are supported. The following example shows how to configure the Linux environment variable (e.g., **.profile**, **.cshrc**, **.bashrc**, **.bash_profile**, etc.). * An example of installing 64 Bit JDK 1.6 and configuring the environment variables in a bash shell :: % JAVA_HOME=/usr/java/jdk1.6.0_10 % LD_LIBRARY_PATH=$JAVA_HOME/jre/lib/amd64:$JAVA_HOME/jre/lib/amd64/server:$LD_LIBRARY_PATH % export JAVA_HOME % export LD_LIBRARY_PATH * An example of installing 32 Bit JDK 1.6 and configuring the environment variables in a bash shell :: % JAVA_HOME=/usr/java/jdk1.6.0_10 % LD_LIBRARY_PATH=$JAVA_HOME/jre/lib/i386/:$JAVA_HOME/jre/lib/i386/client:$LD_LIBRARY_PATH % export JAVA_HOME % export LD_LIBRARY_PATH * An example of installing 64 Bit JDK 1.6 and configuring the environment variables in a csh :: % setenv JAVA_HOME /usr/java/jdk1.6.0_10 % setenv LD_LIBRARY_PATH $JAVA_HOME/jre/lib/amd64:$JAVA_HOME/jre/lib/amd64/server:$LD_LIBRARY_PATH % set path=($path $JAVA_HOME/bin .) * An example of installing 32 Bit JDK 1.6 and configuring the environment variables in a csh shell :: % setenv JAVA_HOME /usr/java/jdk1.6.0_10 % setenv LD_LIBRARY_PATH $JAVA_HOME/jre/lib/i386:$JAVA_HOME/jre/lib/i386/client:$LD_LIBRARY_PATH % set path=($path $JAVA_HOME/bin .) To use other vendor's implementation instead of Sun's Java Virtual Machine, add the path of the JVM (**libjvm.so**) to the library path during the installation. The path of the **libjvm.so** file can be different depending on the platform. For example, the path is the **$JAVA_HOME/jre/lib/sparc** directory in a SUN Sparc machine. How to Write Java Stored Function/Procedure =========================================== Check the cubrid.conf file -------------------------- By default, the **java_stored_procedure** is set to **no** in the **cubrid.conf** file. To use a Java stored function/procedure, this value must be changed to **yes**. For details on this value, see `Other Parameters <#pm_pm_db_classify_etc_htm>`_ in Database Server Configuration. Write and compile the Java source code -------------------------------------- Compile the SpCubrid.java file as follows: .. code-block:: java public class SpCubrid{ public static String HelloCubrid() { return "Hello, Cubrid !!"; } public static int SpInt(int i) { return i + 1; } public static void outTest(String[] o) { o[0] = "Hello, CUBRID"; } } :: javac SpCubrid.java Here, the Java class method must be public static. Load the compiled Java class into CUBRID ---------------------------------------- Load the compiled Java class into CUBRID. :: % loadjava demodb Publish the loaded Java class ----------------------------- Create a CUBRID stored function and publish the Java class as shown below. .. code-block:: sql create function hello() return string as language java name 'SpCubrid.HelloCubrid() return java.lang.String'; Call the Java stored function/procedure --------------------------------------- Call the published Java stored function as follows: .. code-block:: sql call hello() into :Hello; Result ====================== 'Hello, Cubrid !!' Using Server-side Internal JDBC Driver ====================================== To access the database from a Java stored function/procedure, you must use the server-side JDBC driver. As Java stored functions/procedures are executed within the database, there is no need to make the connection to the server-side JDBC driver again. To acquire a connection to the database using the server-side JDBC driver, you can either use "**jdbc:default:connection:**" as the URL for JDBC connection, or call the **getDefaultConnection** () method of the **cubrid.jdbc.driver.CUBRIDDriver** class. .. code-block:: java Class.forName("cubrid.jdbc.driver.CUBRIDDriver"); Connection conn = DriverManager.getConnection("jdbc:default:connection:"); or .. code-block:: java cubrid.jdbc.driver.CUBRIDDriver.getDefaultConnection(); If you connect to the database using the JDBC driver as shown above, the transaction in the Java stored function/procedure is ignored. That is, database operations executed in the Java stored function/procedure belong to the transaction that called the Java stored function/procedure. In the following example, **conn.commit()** method of the **Athlete** class is ignored. .. code-block:: java import java.sql.*; public class Athlete{ public static void Athlete(String name, String gender, String nation_code, String event) throws SQLException{ String sql="INSERT INTO ATHLETE(NAME, GENDER, NATION_CODE, EVENT)" + "VALUES (?, ?, ?, ?)"; try{ Class.forName("cubrid.jdbc.driver.CUBRIDDriver"); Connection conn = DriverManager.getConnection("jdbc:default:connection:"); PreparedStatement pstmt = conn.prepareStatement(sql); pstmt.setString(1, name); pstmt.setString(2, gender); pstmt.setString(3, nation_code); pstmt.setString(4, event);; pstmt.executeUpdate(); pstmt.close(); conn.commit(); conn.close(); } catch (Exception e) { System.err.println(e.getMessage()); } } } Connecting to Other Database ============================ You can connect to another outside database instead of the currently connected one even when the server-side JDBC driver is being used. Acquiring a connection to an outside database is not different from a generic JDBC connection. For details, see JDBC API. If you connect to other databases, the connection to the CUBRID database does not terminate automatically even when the execution of the Java method ends. Therefore, the connection must be explicitly closed so that the result of transaction operations such as **COMMIT** or **ROLLBACK** will be reflected in the database. That is, a separate transaction will be performed because the database that called the Java stored function/procedure is different from the one where the actual connection is made. .. code-block:: java import java.sql.*; public class SelectData { public static void SearchSubway(String[] args) throws Exception { Connection conn = null; Statement stmt = null; ResultSet rs = null; try { Class.forName("cubrid.jdbc.driver.CUBRIDDriver"); conn = DriverManager.getConnection("jdbc:CUBRID:localhost:33000:demodb:::","",""); String sql = "select line_id, line from line"; stmt = conn.createStatement(); rs = stmt.executeQuery(sql); while(rs.next()) { int host_year = rs.getString("host_year"); String host_nation = rs.getString("host_nation"); System.out.println("Host Year ==> " + host_year); System.out.println(" Host Nation==> " + host_nation); System.out.println("\n=========\n"); } rs.close(); stmt.close(); conn.close(); } catch ( SQLException e ) { System.err.println(e.getMessage()); } catch ( Exception e ) { System.err.println(e.getMessage()); } finally { if ( conn != null ) conn.close(); } } } When the Java stored function/procedure being executed should run only on JVM located in the database server, you can check where it is running by calling System.getProperty ("cubrid.server.version") from the Java program source. The result value is the database version if it is called from the database; otherwise, it is **NULL**. loadjava Utility ================ To load a compiled Java or JAR (Java Archive) file into CUBRID, use the **loadjava** utility. If you load a Java \*.class or \*.jar file using the **loadjava** utility, the file is moved to the specified database path. :: loadjava